home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / VELENG10.ZIP / IA_MAIN.C < prev    next >
C/C++ Source or Header  |  1997-07-27  |  19KB  |  987 lines

  1. // ****************************************************************************
  2. // *                                                                          *
  3. // *                      Velena Source Code V1.0                             *
  4. // *                   Written by Giuliano Bertoletti                         *
  5. // *       Based on the knowledged approach of Louis Victor Allis             *
  6. // *   Copyright (C) 1996-97 by Giuliano Bertoletti & GBE 32241 Software PR   *
  7. // *                                                                          *
  8. // ****************************************************************************
  9.  
  10. // Portable engine version.
  11. // read the README file for further informations.
  12.  
  13. // ==========================================================================
  14.  
  15.  
  16. #include <stdio.h>
  17. #include <string.h>
  18. #include <stdlib.h>
  19. #include <malloc.h>
  20. #include <time.h>
  21.  
  22. #include "connect4.h"
  23. #include "con4vals.h"
  24. #include "pnsearch.h"
  25. #include "proto.h"
  26.  
  27. #define BLSTRSIZE 14
  28.  
  29. short maxdepth;
  30.  
  31. short get_black_best_move(struct board *board)
  32.     {
  33.     short black_str[BLSTRSIZE]={4,4,4,4,4,2,2,2,2,6,6,6,6,6};
  34.     short x,flag=YES;
  35.  
  36.     if(board->filled>=BLSTRSIZE) return -1;
  37.  
  38.     for(x=0;x<board->filled && flag;x++)
  39.         if(board->moves[x]!=(black_str[x]-1)) flag=NO;
  40.  
  41.     if(flag) return black_str[board->filled]-1;
  42.  
  43.     return -1;
  44.     }
  45.  
  46. void reverse_board(struct board *board)
  47.     {
  48.     short x,y,z;
  49.  
  50.     for(y=0;y<BOARDY;y++)
  51.         for(x=0;x<BOARDX/2;x++)
  52.             {
  53.             z=board->square[ELM(x,y)];
  54.             board->square[ELM(x,y)]=board->square[ELM(BOARDX-x-1,y)];
  55.             board->square[ELM(BOARDX-x-1,y)]=z;
  56.             }
  57.  
  58.     for(x=0;x<BOARDX/2;x++)
  59.         {
  60.         z=board->stack[x];
  61.         board->stack[x]=board->stack[BOARDX-x-1];
  62.         board->stack[BOARDX-x-1]=z;
  63.         }
  64.     }
  65.  
  66. short pentas(struct board *board,short x,short y,short side)
  67.     {
  68.     if(board->stack[x]>=y) return NO;
  69.     if(board->stack[x+2]>=y) return NO;
  70.     if(board->stack[x+4]>=y) return NO;
  71.  
  72.     if(board->square[ELM(x+1,y)]!=side) return NO;
  73.     if(board->square[ELM(x+3,y)]!=side) return NO;
  74.  
  75.     return YES;
  76.     }
  77.  
  78. short check_pentas(struct board *board,short side)
  79.     {
  80.     short x,y,px,py,flag=0;
  81.  
  82.     for(x=0;x<3 && !flag;x++)
  83.         for(y=0;y<2 && !flag;y++)
  84.             {
  85.             px=x;
  86.             py=(y+1)*2;
  87.  
  88.             flag=(flag || pentas(board,px,py,side));
  89.             }
  90.  
  91.     return flag;
  92.     }
  93.  
  94. short gen_odd_threat(struct board *board,short x,short side)
  95.     {
  96.     short y,empty=0,fill=0,emp[TILES],px,py;
  97.  
  98.     for(y=0;y<TILES;y++)
  99.         {
  100.         if(*board->groups[x][y]==EMPTY)
  101.             {
  102.             px=board->xplace[x][y];
  103.             py=board->yplace[x][y];
  104.             emp[empty++]=ELM(px,py);
  105.             }
  106.         else if (*board->groups[x][y]==side) fill++;
  107.         }
  108.  
  109.     if(empty==1 && fill==3 && (py&1)==0 && board->stack[px]<py) return emp[0];
  110.     return -1;
  111.     }
  112.  
  113. short check_double(struct board *board,short group,short pos,short side)
  114.     {
  115.     short x,y;
  116.  
  117.     for(x=group+1;x<GROUPS;x++)
  118.         {
  119.         y=gen_odd_threat(board,x,side);
  120.         if(y==pos) return YES;
  121.         }
  122.  
  123.     return NO;
  124.     }
  125.  
  126. short groupeval(struct board *board)
  127.     {
  128.     short x,v1,v2;
  129.     short z,f,p1,p2,t1,t2,score=0;
  130.  
  131.     t1=board->turn;
  132.     t2=board->turn^SWITCHSIDE;
  133.  
  134.     for(x=0;x<GROUPS;x++)
  135.         {
  136.         p1=0;
  137.         p2=0;
  138.  
  139.         if     (*board->groups[x][0]==t1) p1++;
  140.         else if(*board->groups[x][0]==t2) p2++;
  141.  
  142.         if     (*board->groups[x][1]==t1) p1++;
  143.         else if(*board->groups[x][1]==t2) p2++;
  144.  
  145.         if     (*board->groups[x][2]==t1) p1++;
  146.         else if(*board->groups[x][2]==t2) p2++;
  147.  
  148.         if     (*board->groups[x][3]==t1) p1++;
  149.         else if(*board->groups[x][3]==t2) p2++;
  150.  
  151.         if(p1==4) return GOODMOVE;
  152.         if(p2==4) return BADMOVE;
  153.  
  154.         if(p1==3 && p2==0)
  155.             {
  156.             score+=100;
  157.             z=gen_odd_threat(board,x,t1);
  158.             if(z!=-1)
  159.                 {
  160.                 f=check_double(board,x,z,t1);
  161.                 if(!f)
  162.                     {
  163.                     if(t1==WHITE) score+=200;
  164.                     else score+=150;
  165.                     }
  166.                 else
  167.                     {
  168.                     if(t1==WHITE) score+=750;
  169.                     else score+=500;
  170.                     }
  171.                 }
  172.             }
  173.  
  174.         if(p2==3 && p1==0)
  175.             {
  176.             score-=100;
  177.             z=gen_odd_threat(board,x,t2);
  178.             if(z!=-1)
  179.                 {
  180.                 f=check_double(board,x,z,t2);
  181.                 if(!f)
  182.                     {
  183.                     if(t1==BLACK) score-=200;
  184.                     else score-=150;
  185.                     }
  186.                 else
  187.                     {
  188.                     if(t1==BLACK) score-=750;
  189.                     else score-=500;
  190.                     }
  191.                 }
  192.             }
  193.  
  194.         if(p1==2 && p2==0) score+=10;
  195.         if(p2==2 && p1==0) score-=10;
  196.         }
  197.  
  198.  
  199.     if(check_pentas(board,WHITE))
  200.         {
  201.         if(t1==WHITE) score+=800;
  202.         else score-=800;
  203.         }
  204.  
  205.     return score;
  206.     }
  207.  
  208. short connected(struct board *board,short move)
  209.     {
  210.     short maxcon=1;
  211.     short px,py,connect;
  212.  
  213.     /* Check vertical */
  214.  
  215.     connect=1;
  216.  
  217.     px=move;
  218.     py=board->stack[move]-1;
  219.  
  220.     while(py>=0 && board->square[ELM(px,py)]==board->turn)
  221.         {
  222.         connect++;
  223.         py--;
  224.         }
  225.  
  226.     maxcon=max(connect,maxcon);
  227.  
  228.     /* Check horizontal */
  229.  
  230.     connect=1;
  231.  
  232.     px =move-1;
  233.     py =board->stack[move];
  234.  
  235.     while(px>=0 && board->square[ELM(px,py)]==board->turn)
  236.         {
  237.         connect++;
  238.         px--;
  239.         }
  240.  
  241.     px=move+1;
  242.  
  243.     while(px<BOARDX && board->square[ELM(px,py)]==board->turn)
  244.         {
  245.         connect++;
  246.         px++;
  247.         }
  248.  
  249.     maxcon=max(connect,maxcon);
  250.  
  251.     /* Check NW - SE diagonal */
  252.  
  253.     connect=1;
  254.  
  255.     px=move-1;
  256.     py=board->stack[move]+1;
  257.  
  258.     while(px>=0 && py<BOARDY && board->square[ELM(px,py)]==board->turn)
  259.         {
  260.         connect++;
  261.         px--;
  262.         py++;
  263.         }
  264.  
  265.     px=move+1;
  266.     py=board->stack[move]-1;
  267.  
  268.     while(px<BOARDX && py>=0 && board->square[ELM(px,py)]==board->turn)
  269.         {
  270.         connect++;
  271.         px++;
  272.         py--;
  273.         }
  274.  
  275.     maxcon=max(connect,maxcon);
  276.  
  277.     /* Check NE - SW */
  278.  
  279.     connect=1;
  280.  
  281.     px=move-1;
  282.     py=board->stack[move]-1;
  283.  
  284.     while(px>=0 && py>=0 && board->square[ELM(px,py)]==board->turn)
  285.         {
  286.         connect++;
  287.         px--;
  288.         py--;
  289.         }
  290.  
  291.     px=move+1;
  292.     py=board->stack[move]+1;
  293.  
  294.     while(px<BOARDX && py<BOARDY && board->square[ELM(px,py)]==board->turn)
  295.         {
  296.         connect++;
  297.         px++;
  298.         py++;
  299.         }
  300.  
  301.     maxcon=max(connect,maxcon);
  302.  
  303.     return maxcon;
  304.     }
  305.  
  306. short opponent_connected(struct board *board,short move)
  307.     {
  308.     short con;
  309.  
  310.     board->turn^=SWITCHSIDE;
  311.     con=connected(board,move);
  312.     board->turn^=SWITCHSIDE;
  313.  
  314.     return con;
  315.     }
  316.  
  317.  
  318. short makemove(struct board *board,short move)
  319.     {
  320.     if(board->stack[move]>=6) return 0;
  321.  
  322.     board->square[ELM(move,board->stack[move]++)]=board->turn;
  323.     board->moves[board->filled]=move;
  324.     board->mlist[board->filled]=ELM(move,board->stack[move]);
  325.     board->turn^=SWITCHSIDE;
  326.     board->filled++;
  327.  
  328.     return 1;
  329.     }
  330.  
  331. short undomove(struct board *board,short move)
  332.     {
  333.     if(board->stack[move]<1) return 0;
  334.  
  335.     board->square[ELM(move,--board->stack[move])]=EMPTY;
  336.     board->turn^=SWITCHSIDE;
  337.     board->filled--;
  338.     board->moves[board->filled]=-1;
  339.     board->mlist[board->filled]=-1;
  340.  
  341.     return 1;
  342.     }
  343.  
  344. int get_game_result(struct board *board)
  345.     {
  346.     short answer=-1;
  347.     short i;
  348.  
  349.     for(i=0;i<GROUPS && answer==-1;i++)
  350.         {
  351.         if (*board->groups[i][0]!=EMPTY &&
  352.             *board->groups[i][0]==*board->groups[i][1] &&
  353.             *board->groups[i][0]==*board->groups[i][2] &&
  354.             *board->groups[i][0]==*board->groups[i][3])
  355.                 {
  356.                 if(*board->groups[i][0]==WHITE) answer=WHITE;
  357.                 else answer=BLACK;
  358.                 }
  359.         }
  360.  
  361.     if(board->filled==MAXSQUARES && answer==-1) answer=0;
  362.     return answer;
  363.     }
  364.  
  365. short endgame(struct board *board)
  366.     {
  367.     short answer=NOTHING;
  368.     short i,j;
  369.  
  370.     for(i=0;i<GROUPS && answer==NOTHING;i++)
  371.         {
  372.         if(*board->groups[i][0]!=EMPTY &&
  373.             *board->groups[i][0]==*board->groups[i][1] &&
  374.             *board->groups[i][0]==*board->groups[i][2] &&
  375.             *board->groups[i][0]==*board->groups[i][3]) answer=WIN;
  376.  
  377.         j=*board->groups[i][0];
  378.         }
  379.  
  380.     if(board->filled==MAXSQUARES && answer==NOTHING)
  381.         {
  382.         answer=DRAW;
  383.         board->lastwin=0;
  384.         }
  385.  
  386.     if(answer==WIN)
  387.         {
  388.         board->wins[j-1]++;
  389.         board->lastwin=j;
  390.         if(board->oracle[2-j]==YES)
  391.             fatal_error("Oracle failed to tell the truth");
  392.         }
  393.  
  394.     else if(answer==DRAW) board->draws++;
  395.  
  396.     return answer;
  397.     }
  398.  
  399. short try_to_win(struct board *board)
  400.     {
  401.     short x,av[BOARDX],win=NO;
  402.  
  403.     for(x=0;x<BOARDX;x++)
  404.         {
  405.         if(board->stack[x]<BOARDY && connected(board,x)>=4)
  406.             {
  407.             av[x]=YES;
  408.             win=YES;
  409.             }
  410.         else av[x]=NO;
  411.         }
  412.  
  413.     if(win)
  414.         {
  415.         do
  416.             {
  417.             x=my_random(BOARDX);
  418.             } while(av[x]==NO);
  419.         }
  420.     else x=-1;
  421.  
  422.     return x;
  423.     }
  424.  
  425.  
  426. short fast_try_to_win(struct board *board)
  427.     {
  428.     short x,win=-1;
  429.  
  430.     for(x=0;x<BOARDX;x++)
  431.         if(board->stack[x]<BOARDY && connected(board,x)>=4) win=x;
  432.  
  433.     return win;
  434.     }
  435.  
  436. short avoid_tricks(struct board *board,short side)
  437.     {
  438.     short x,answ,cn=0,tmp;
  439.  
  440.     maxdepth++;
  441.  
  442.     if(board->turn!=side)
  443.         {
  444.         answ=GOODMOVE;
  445.  
  446.         for(x=0;x<BOARDX;x++)
  447.             {
  448.             if(board->stack[x]<BOARDY)
  449.                 {
  450.                 cn++;
  451.                 if(connected(board,x)>=4)
  452.                     {
  453.                     maxdepth--;
  454.                     return BADMOVE;
  455.                     }
  456.                 else
  457.                     {
  458.                     makemove(board,x);
  459.                     tmp=avoid_tricks(board,side);
  460.                     answ=min(answ,tmp);
  461.                     undomove(board,x);
  462.                     }
  463.                 }
  464.  
  465.             }
  466.  
  467.         if(cn==0) answ=NOCOMMENT;
  468.         }
  469.  
  470.     else
  471.         {
  472.         answ=GOODMOVE;
  473.  
  474.         for(x=0;x<BOARDX;x++)
  475.             {
  476.             if(board->stack[x]<BOARDY)
  477.                 {
  478.                 cn++;
  479.                 if(connected(board,x)>=4)
  480.                     {
  481.                     maxdepth--;
  482.                     return GOODMOVE;
  483.                     }
  484.                 else if(opponent_connected(board,x)>=4)
  485.                     {
  486.                     makemove(board,x);
  487.                     tmp=avoid_tricks(board,side);
  488.                     answ=min(answ,tmp);
  489.                     undomove(board,x);
  490.                     }
  491.                 }
  492.             }
  493.  
  494.         if(cn==0) answ=NOCOMMENT;
  495.         }
  496.  
  497.     maxdepth--;
  498.  
  499.     return answ;
  500.     }
  501.  
  502. short play_tricks(struct board *board,short side)
  503.     {
  504.     short tmp;
  505.  
  506.     tmp=avoid_tricks(board,side^SWITCHSIDE);
  507.  
  508.     switch(tmp)
  509.         {
  510.         case GOODMOVE:
  511.             tmp=BADMOVE;
  512.             break;
  513.  
  514.         case BADMOVE:
  515.             tmp=GOODMOVE;
  516.             break;
  517.         }
  518.  
  519.     return tmp;
  520.     }
  521.  
  522. short save_position(struct board *board)
  523.     {
  524.     short x,y=GOODMOVE,z=IMPOSSIBLE,pos,score[BOARDX];
  525.  
  526.     for(x=0;x<BOARDX;x++)
  527.         {
  528.         score[x]=IMPOSSIBLE;
  529.         if(board->stack[x]<BOARDY)
  530.             {
  531.             makemove(board,x);
  532.             score[x]=avoid_tricks(board,board->turn^SWITCHSIDE);
  533.             y=min(score[x],y);
  534.             z=max(score[x],z);
  535.             undomove(board,x);
  536.             }
  537.         }
  538.  
  539.     if(y<GOODMOVE)
  540.         {
  541.         do
  542.             {
  543.             pos=my_random(BOARDX);
  544.             } while(score[pos]!=z);
  545.         }
  546.  
  547.     else pos=-1;
  548.  
  549.     return pos;
  550.     }
  551.  
  552. short explore_tree(struct board *board,short side,short depth)
  553.     {
  554.     short x,c,answ,cn=0,tmp;
  555.  
  556.     if(depth==0)
  557.         {
  558.         tmp=groupeval(board);
  559.         if(board->turn==side) return tmp;
  560.         else return -tmp;
  561.         }
  562.  
  563.     /*
  564.     if((depth==DEPTH-1) && avoid_tricks(board,side)==BADMOVE)
  565.         return BADMOVE;
  566.  
  567.  
  568.     if((depth==DEPTH-1) && play_tricks(board,side)==GOODMOVE)
  569.         return GOODMOVE;
  570.    */
  571.     maxdepth++;
  572.  
  573.     if(board->turn!=side)
  574.         {
  575.         answ=GOODMOVE-depth;
  576.  
  577.         for(x=0;x<BOARDX && answ!=BADMOVE;x++)
  578.             {
  579.             if(board->stack[x]<BOARDY)
  580.                 {
  581.                 cn++;
  582.                 if(connected(board,x)>=4) answ=BADMOVE;
  583.                 else
  584.                     {
  585.                     makemove(board,x);
  586.                     tmp=explore_tree(board,side,depth-1);
  587.                     answ=min(answ,tmp);
  588.                     undomove(board,x);
  589.                     }
  590.                 }
  591.  
  592.             }
  593.  
  594.         if(cn==0) answ=NOCOMMENT;
  595.         }
  596.  
  597.     else
  598.         {
  599.         answ=BADMOVE+depth;
  600.  
  601.         for(x=0;x<BOARDX;x++)
  602.             {
  603.             if(board->stack[x]<BOARDY)
  604.                 {
  605.                 cn++;
  606.                 if(connected(board,x)>=4) answ=GOODMOVE;
  607.                 else
  608.                     {
  609.                     makemove(board,x);
  610.                     tmp=explore_tree(board,side,depth-1);
  611.                     answ=max(answ,tmp);
  612.                     undomove(board,x);
  613.                     }
  614.                 }
  615.             }
  616.  
  617.         if(cn==0) answ=NOCOMMENT;
  618.         }
  619.  
  620.     maxdepth--;
  621.  
  622.     return answ;
  623.     }
  624.  
  625. short look_ahed(struct board *board)
  626.     {
  627.     long def_nodes=0L;
  628.     short x,y,score[BOARDX],sc=IMPOSSIBLE,p;
  629.     short depth=DEPTH,oracle,set=NO,def_depth=0,cpu_level;
  630.  
  631.     maxdepth=0;
  632.  
  633.     if(board->turn==WHITE) cpu_level=board->white_lev;
  634.     else cpu_level=board->black_lev;
  635.  
  636.     for(x=0;x<BOARDX;x++)
  637.         {
  638.         score[x]=IMPOSSIBLE;
  639.         if(board->stack[x]<BOARDY)
  640.             {
  641.             makemove(board,x);
  642.  
  643.             p=heuristic_play_best(board,2800L);
  644.             def_nodes+=board->nodes_visited;
  645.             def_depth=max(def_depth,board->maxtreedepth);
  646.  
  647.             if(p>=0) score[x]=BADMOVE+board->maxtreedepth;
  648.             else if(p==-2) score[x]=GOODMOVE-board->maxtreedepth;
  649.             else
  650.                 {
  651.                 score[x]=explore_tree(board,board->turn^SWITCHSIDE,depth-1);
  652.                 if(score[x]>-3500 && score[x]<3500)
  653.                     {
  654.                     if(board->autotest) score[x]=my_random(RANDVARIANCE);
  655.                     else score[x]+=my_random(RANDVARIANCE);
  656.                     }
  657.  
  658.                 if(cpu_level>1) oracle=evaluation_function(board);
  659.                 else oracle=0;
  660.  
  661.                 score[x]+=(oracle<<13);
  662.                 if(oracle)
  663.                     {
  664.                     set=YES;
  665.                     if(!board->oracle[2-board->turn])
  666.                         {
  667.                         board->lastguess=board->filled+1;
  668.                         board->oracle[2-board->turn]=YES;
  669.                         if(board->lastguess<board->bestguess)
  670.                             board->bestguess=board->lastguess;
  671.                         }
  672.                     }
  673.                 }
  674.             undomove(board,x);
  675.             }
  676.  
  677.         sc=max(score[x],sc);
  678.         }
  679.  
  680.     for(x=0,y=0;x<BOARDX;x++)
  681.         if(score[x]==sc) y++;
  682.  
  683.     board->choices[board->filled]=y;
  684.  
  685.     do
  686.         {
  687.         x=my_random(BOARDX);
  688.         } while(score[x]!=sc);
  689.  
  690.     return x;
  691.     }
  692.  
  693. short defending_function(struct board *board)
  694.     {
  695.     int x,y=0;
  696.  
  697.     for(x=0;x<BOARDX;x++)
  698.         {
  699.         if(board->stack[x]<BOARDY)
  700.             {
  701.             makemove(board,x);
  702.             if(evaluation_function(board) ||
  703.                heuristic_play_best(board,2800L)>=0)
  704.                   y++;
  705.             undomove(board,x);
  706.             }
  707.         else y++;
  708.         }
  709.  
  710.     if(y<BOARDX) return 0;
  711.     return 1;
  712.     }
  713.  
  714. short heuristic_defend_best(struct board *board)
  715.     {
  716.     int x,y=0;
  717.  
  718.     for(x=0;x<BOARDX;x++)
  719.         {
  720.         if(board->stack[x]<BOARDY)
  721.             {
  722.             makemove(board,x);
  723.             if(heuristic_play_best(board,2800L)>=0) y++;
  724.             undomove(board,x);
  725.             }
  726.         else y++;
  727.         }
  728.  
  729.     if(y<BOARDX) return -1;
  730.     return 1;
  731.     }
  732.  
  733. short mybincmp(unsigned char *p1,unsigned char *p2,short len)
  734.     {
  735.     short x;
  736.  
  737.     for(x=0;x<len;x++)
  738.         {
  739.         if(p1[x]<p2[x]) return -1;
  740.         else if(p1[x]>p2[x]) return +1;
  741.         }
  742.  
  743.     return 0;
  744.     }
  745.  
  746. short check_book(struct board *board,unsigned char *cmparray,short side)
  747.     {
  748.     short res,value;
  749.     long x,head,tail;
  750.  
  751.     head=0;
  752.     tail=board->wbposit;
  753.  
  754.     if(side==WHITE) value=PROVED;
  755.     else value=DISPROVED;
  756.  
  757.     cmparray[12]=(value)&255;
  758.     cmparray[13]=(value)>>8;
  759.  
  760.     do
  761.         {
  762.         x=(head + tail)/2;
  763.         res=mybincmp(cmparray,&board->white_book[14*x],14);
  764.         if(res==1) head=x+1;
  765.         else if(res==-1) tail=x;
  766.         } while(res!=0 && head!=tail);
  767.  
  768.     if(res==0)
  769.         {
  770.         board->lastob=x;
  771.         return YES;
  772.         }
  773.     return NO;
  774.     }
  775.  
  776. short get_lower(short *bb,unsigned char *tp)
  777.     {
  778.     char tp2[64];
  779.  
  780.     short x,y,flag=0;
  781.  
  782.     memset(tp,0xff,64);
  783.     memset(tp2,0xff,64);
  784.  
  785.     for(y=0;y<BOARDY;y++)
  786.         for(x=0;x<BOARDX;x++)
  787.             {
  788.             tp [ELM(x,y)]=bb[ELM(x,y)];
  789.             tp2[ELM(x,y)]=bb[ELM(BOARDX-x-1,y)];
  790.             }
  791.  
  792.     for(x=0;x<64 && flag==0;x++)
  793.         {
  794.         if(tp[x]<tp2[x]) flag=-1;
  795.         else if(tp[x]>tp2[x]) flag=1;
  796.         }
  797.  
  798.     if(flag==1)
  799.         {
  800.         memcpy(tp,tp2,64);
  801.         return 0;
  802.         }
  803.  
  804.     return 1;
  805.     }
  806.  
  807. short use_opening_book(struct board *board,short side)
  808.     {
  809.     char flags[BOARDX],flagno=0;
  810.     unsigned char cmparray[14];
  811.     unsigned char tempboard[64];
  812.     short x;
  813.  
  814.     if(!board->white_book) return -1;
  815.  
  816.     for(x=0;x<BOARDX;x++)
  817.         {
  818.         flags[x]=NO;
  819.         if(makemove(board,x))
  820.             {
  821.             get_lower(board->square,tempboard);
  822.             collapse_position(tempboard,cmparray);
  823.             if(check_book(board,cmparray,side))
  824.                 {
  825.                 flags[x]=YES;
  826.                 flagno++;
  827.                 }
  828.             undomove(board,x);
  829.             }
  830.         }
  831.  
  832.     if(flagno) while(1)
  833.         {
  834.         x=my_random(BOARDX);
  835.         if(flags[x]) return x;
  836.         }
  837.  
  838.     return -1;
  839.     }
  840.  
  841. short check_presence(struct board *board,short side)
  842.     {
  843.     unsigned char tempboard[64],cmparray[14];
  844.  
  845.     get_lower(board->square,tempboard);
  846.     collapse_position(tempboard,cmparray);
  847.     return check_book(board,cmparray,side);
  848.     }
  849.  
  850. short avoid_immediate_loss(struct board *board)
  851.         {
  852.         short move;
  853.  
  854.         board->turn^=SWITCHSIDE;
  855.         move=try_to_win(board);
  856.         board->turn^=SWITCHSIDE;
  857.         return move;
  858.         }
  859.  
  860. short ia_compute_move(struct board *board)
  861.     {
  862.     short move,x,y;
  863.  
  864.     board->choices[board->filled]=1;
  865.  
  866.         if(board->filled==0)
  867.         {
  868.         move=3;
  869.         goto IA_RETURN_MOVE;
  870.         }
  871.  
  872.     if(board->filled==1)
  873.         {
  874.         move=3;
  875.         if(board->moves[0]==1) move=2;
  876.         else if(board->moves[0]==5) move=4;
  877.         goto IA_RETURN_MOVE;
  878.         }
  879.  
  880.     if(board->filled==MAXMEN-1)
  881.         {
  882.         for(x=0;x<BOARDX;x++)
  883.             {
  884.             if(board->stack[x]<BOARDY)
  885.                 {
  886.                 move=x;
  887.                 goto IA_RETURN_MOVE;
  888.                 }
  889.             }
  890.         fatal_error("I shouldn't have come here...");
  891.         }
  892.     
  893.     move=try_to_win(board);
  894.     if(move>=0) goto IA_RETURN_MOVE;
  895.  
  896.     move=avoid_immediate_loss(board);
  897.     if(move>=0) goto IA_RETURN_MOVE;
  898.     
  899.     if(board->turn==BLACK && board->black_lev==3)
  900.         {
  901.         move=get_black_best_move(board);
  902.         if(move>=0) goto IA_RETURN_MOVE;
  903.         }
  904.  
  905.     else if(board->filled==1 && board->stack[3]==1)
  906.         {
  907.         if(board->autotest)
  908.             {
  909.             short sel;
  910.  
  911.             /* The probability should not be uniform, but triangular */
  912.             sel=my_random(15);
  913.  
  914.             if(sel==0) move=0;
  915.             else if(sel<= 2) move=1;
  916.             else if(sel<= 5) move=2;
  917.             else if(sel<= 9) move=3;
  918.             else if(sel<=12) move=4;
  919.             else if(sel<=14) move=5;
  920.             else move=6;
  921.             }
  922.         else move=3;
  923.  
  924.         goto IA_RETURN_MOVE;
  925.         }
  926.  
  927.     /* Let's look in the opening book */
  928.     switch(board->turn)
  929.         {
  930.         case WHITE:
  931.             if(board->white_lev==3) move=use_opening_book(board,WHITE);
  932.             else move=-1;
  933.             break;
  934.  
  935.         case BLACK:
  936.             if(board->black_lev==3) move=use_opening_book(board,BLACK);
  937.             else move=-1;
  938.             break;
  939.  
  940.         default:
  941.             fatal_error("I don't know who's to move...");
  942.             break;
  943.         }
  944.  
  945.     if(move>=0) goto IA_RETURN_MOVE;
  946.  
  947.     fight(NO);
  948.     move=heuristic_play_best(board,2800L);
  949.  
  950.     // Here we handle the fact that Black could also look for a win
  951.     // improving the algorithm.
  952.  
  953.     if(board->turn==BLACK)
  954.         {
  955.         short temp;
  956.  
  957.         fight(YES);
  958.         temp=heuristic_play_best(board,2800L);
  959.         fight(NO);
  960.  
  961.         if(temp>=0) move=temp;
  962.         }
  963.  
  964.     if(move>=0) goto IA_RETURN_MOVE;
  965.  
  966.     move=look_ahed(board);
  967.  
  968.     IA_RETURN_MOVE:
  969.     return move;
  970.     }
  971.  
  972. // ***************************************************************************
  973.  
  974. short get_last_move(struct board *board)
  975.     {
  976.     short x,y=-1;
  977.  
  978.     for(x=0;x<BOARDX && y==-1;x++)
  979.         if(board->stack[x]<BOARDY) y=x;
  980.  
  981.     if(y==-1) fatal_error("Problem finding a solution...");
  982.  
  983.     if(connected(board,y)>=4) return 10;
  984.     return 11;
  985.     }
  986.  
  987.